
            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <title>Prometheus Operator 极简配置方式在k8s一条龙安装Prometheus 监控</title>
            </head>
            <body>
            <a href="https://andyoung.blog.csdn.net">原作者博客</a>
            <div id="content_views" class="markdown_views prism-atom-one-light">
                    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
                        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
                    </svg>
                    <blockquote> 
 <p>在k8s上 Prometheus（普罗米修斯） 监控，需要部署各种组件，比如Prometheus、Alertmanager、Grafana。同时各个组件的配置文件也是需要到处各个配置，Prometheus配置监控服务时，你还要知道各个监控服务的地址，地址换了还需要更新， 实在是麻烦。而今天的主角 Prometheus Operator 使用自定义资源的方式来简化Prometheus、Alertmanager配置， 实现自动化部署、自动化服务发现、轻松配置配置等功能。下面我们来一起看看吧。</p> 
</blockquote> 
<h2><a id="Operator_3"></a>Operator</h2> 
<p><code>Operator</code>是由<a href="https://coreos.com/" rel="nofollow">CoreOS</a>公司开发的，用来扩展 Kubernetes API，特定的应用程序控制器，它用来创建、配置和管理复杂的有状态应用，如数据库、缓存和监控系统。<code>Operator</code>基于 Kubernetes 的资源和控制器概念之上构建，但同时又包含了应用程序特定的一些专业知识，比如创建一个数据库的<code>Operator</code>，则必须对创建的数据库的各种运维方式非常了解，创建<code>Operator</code>的关键是<code>CRD</code>（自定义资源）的设计。</p> 
<blockquote> 
 <p><code>CRD</code>是对 Kubernetes API 的扩展，Kubernetes 中的每个资源都是一个 API 对象的集合，例如我们在YAML文件里定义的那些<code>spec</code>都是对 Kubernetes 中的资源对象的定义，所有的自定义资源可以跟 Kubernetes 中内建的资源一样使用 kubectl 操作。</p> 
</blockquote> 
<p><code>Operator</code>是将运维人员对软件操作的知识给代码化，同时利用 Kubernetes 强大的抽象来管理大规模的软件应用。目前<code>CoreOS</code>官方提供了几种<code>Operator</code>的实现，其中就包括我们今天的主角：<code>Prometheus Operator</code>，<code>Operator</code>的核心实现就是基于 Kubernetes 的以下两个概念：</p> 
<ul><li>资源：对象的状态定义</li><li>控制器：观测、分析和行动，以调节资源的分布</li></ul> 
<p>当然我们如果有对应的需求也完全可以自己去实现一个<code>Operator</code>，接下来我们就来给大家详细介绍下<code>Prometheus-Operator</code>的使用方法。</p> 
<h2><a id="_16"></a>介绍</h2> 
<p><a href="https://github.com/prometheus-operator/prometheus-operator">Prometheus Operator</a> 提供<a href="https://kubernetes.io/" rel="nofollow">Kubernetes</a> 原生部署和管理<a href="https://prometheus.io/" rel="nofollow">Prometheus</a>和相关的监控组件。该项目的是简化和自动化配置Prometheus的监控Kubernetes集群。</p> 
<p>Prometheus Operator 包括但不限于以下功能:</p> 
<ul><li>Kubernetes自定义资源:使用Kubernetes自定义资源来部署和管理Prometheus、Alertmanager和相关组件。</li><li>简化的部署配置:从本地Kubernetes资源配置Prometheus的基本功能，如版本、持久性、保留策略和副本。</li><li>Prometheus Target 配置:根据熟悉的Kubernetes标签查询自动生成监控目标配置；无需学习Prometheus专用的配置语言。</li></ul> 
<h3><a id="Prometheus_Operator_vs_kubeprometheus_vs_community_helm_chart_26"></a>Prometheus Operator vs. kube-prometheus vs. community helm chart</h3> 
<ul><li>Prometheus Operator：使用Kubernetes<a href="https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/" rel="nofollow">自定义资源</a>简化Prometheus、Alertmanager和相关监视组件的部署和配置。</li><li>kube-prometheus：<a href="https://github.com/prometheus-operator/kube-prometheus">kube-prometheus</a>提供了基于Prometheus和Prometheus Operator的完整集群监视堆栈的示例配置。这包括部署多个Prometheus和Alertmanager实例、用于收集节点指标的node_exporter等指标exporte、将Prometheus链接到各种指标端点的临时目标配置，以及用于通知集群中潜在问题的示例警报规则。</li><li>helm chart：这<a href="https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack">prometheus-community/helm-charts</a> 提供了一个类似于Prometheus Operator的功能集。该helm chart由Prometheus 社区维护。</li></ul> 
<h2><a id="Prometheus_Operator_CRD_32"></a>Prometheus Operator CRD介绍</h2> 
<p>Prometheus Operator 的目标是尽可能容易地在Kubernetes上运行Prometheus，同时保留Kubernetes本地配置选项。</p> 
<p>本指南将向您展示如何部署Prometheus操作符、设置Prometheus实例以及为一个示例应用程序配置度量收集。</p> 
<blockquote> 
 <p>Prometheus Operator 要求使用 Kubernetes 版本 v1.16.x 及以上.</p> 
</blockquote> 
<p>Prometheus Operator 在Kubernetes中引入了自定义资源，以声明Prometheus和Alertmanager集群以及Prometheus配置的理想状态。prometheus-operator的使用，基本是如何操作下述的CRD对象。:</p> 
<ul><li> <p><code>Prometheus</code>: 对prometheus-server的部署</p> </li><li> <p><code>ServiceMonitor</code>: 对service监控对象的抽象；它声明性地指定了应该如何监控Kubernetes services 组。Operator 根据API服务器中对象的当前状态自动生成Prometheus scrape配置（scrape_configs）。</p> </li><li> <p><code>PodMonitor</code>: 对pod监控对象的抽象；它声明性地指定了应该如何监控一组pod。Operator 根据API服务器中对象的当前状态自动生成Prometheus scrape配置。</p> </li><li> <p><strong><code>PrometheusRule</code></strong>: 对prometheus报警规则的抽象；其定义了一组期望的Prometheus 警报和/或记录规则。Operator 生成一个Prometheus实例可以使用的规则文件。</p> </li><li> <p><strong><code>Alertmanager</code></strong>：它定义了所需的Alertmanager部署。</p> </li><li> <p><strong><code>AlertmanagerConfig</code></strong>： 它以声明方式指定Alertmanager配置的子部分，允许将警报路由到自定义接收器，并设置禁止规则。</p> </li><li> <p><strong><code>ThanosRuler</code></strong>： 它定义了所需的Thanos 规则部署</p> </li><li> <p><strong><code>Probe</code></strong>： 它以声明方式指定应该如何监视入侵组或静态目标组。操作员根据定义自动生成普罗米修斯刮削配置。</p> </li></ul> 
<p>这<code>Prometheus</code>资源声明性地描述了Prometheus部署的期望状态，而<code>ServiceMonitor</code>和<code>PodMonitor</code>资源描述了Prometheus监控的<code>targets</code> 。</p> 
<p><strong>Prometheus Operator 架构图</strong></p> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/b766d983e6cf3a40a343b273271b2ca9.png#pic_center" alt="Prometheus Operator 架构图"></p> 
<p>上图是<code>Prometheus-Operator</code>官方提供的架构图，其中<code>Operator</code>是最核心的部分，作为一个控制器，他会去创建<code>Prometheus</code>、<code>ServiceMonitor</code>、<code>AlertManager</code>以及<code>PrometheusRule</code>4个<code>CRD</code>资源对象，然后会一直监控并维持这4个资源对象的状态。</p> 
<p>其中创建的<code>prometheus</code>这种资源对象就是作为<code>Prometheus Server</code>存在，而<code>ServiceMonitor</code>就是<code>exporter</code>的各种抽象，<code>exporter</code>前面我们已经学习了，是用来提供专门提供<code>metrics</code>数据接口的工具，<code>Prometheus</code>就是通过<code>ServiceMonitor</code>提供的<code>metrics</code>数据接口去 pull 数据的，当然<code>alertmanager</code>这种资源对象就是对应的<code>AlertManager</code>的抽象，而<code>PrometheusRule</code>是用来被<code>Prometheus</code>实例使用的报警规则文件。</p> 
<p>这样我们要在集群中监控什么数据，就变成了直接去操作 Kubernetes 集群的资源对象了，是不是方便很多了。上图中的 Service 和 ServiceMonitor 都是 Kubernetes 的资源，一个 ServiceMonitor 可以通过 labelSelector 的方式去匹配一类 Service，Prometheus 也可以通过 labelSelector 去匹配多个ServiceMonitor。</p> 
<h2><a id="_76"></a>开始使用</h2> 
<p>我们使用 kube-prometheus 来部署 Prometheus Operator，因为他不仅提供了 Prometheus Operator 还提供 Alertmanager、Grafana,node_exporter等组件</p> 
<h3><a id="kubeprometheus_80"></a>获得kube-prometheus项目</h3> 
<p>从GitHub克隆kube-prometheus</p> 
<pre><code>git clone https://github.com/prometheus-operator/kube-prometheus.git
</code></pre> 
<p>或者下载当前主分支的zip文件并提取其内容:</p> 
<p><a href="https://github.com/prometheus-operator/kube-prometheus/archive/main.zip">github . com/Prometheus-operator/kube-Prometheus/archive/main . zip</a></p> 
<p>一旦你下载完成，你就可以进入项目的根目录。</p> 
<h3><a id="_kubeprometheus_94"></a>部署 kube-prometheus</h3> 
<pre><code># Create the namespace and CRDs, and then wait for them to be availble before creating the remaining resources
kubectl create -f manifests/setup

# Wait until the "servicemonitors" CRD is created. The message "No resources found" means success in this context.
until kubectl get servicemonitors --all-namespaces ; do date; sleep 1; echo ""; done

kubectl create -f manifests/
</code></pre> 
<p>我们首先创建namespace和CustomResourceDefinitions，以避免在部署监控组件时出现竞争情况。或者，可以用一个命令应用两个文件夹中的资源<code>kubectl create -f manifests/setup -f manifests</code>，但是可能需要多次运行该命令才能成功创建所有组件。</p> 
<p>查看CRD类型：</p> 
<pre><code>[root@a1 ~]# kubectl get crd |grep coreos
alertmanagerconfigs.monitoring.coreos.com   2022-08-11T01:37:54Z
alertmanagers.monitoring.coreos.com         2022-08-11T01:37:54Z
podmonitors.monitoring.coreos.com           2022-08-11T01:37:54Z
probes.monitoring.coreos.com                2022-08-11T01:37:54Z
prometheuses.monitoring.coreos.com          2022-08-11T01:37:54Z
prometheusrules.monitoring.coreos.com       2022-08-11T01:37:54Z
servicemonitors.monitoring.coreos.com       2022-08-11T01:37:54Z
thanosrulers.monitoring.coreos.com          2022-08-11T01:37:54Z

</code></pre> 
<p>查看特定CRD类型下的实例：</p> 
<pre><code>[root@a1 ~]# kubectl get prometheuses -n monitoring
NAME   VERSION   REPLICAS   AGE
k8s    2.32.1    2          97d
</code></pre> 
<pre><code>[root@a1 ~]# kubectl get servicemonitors -n monitoring
NAME                      AGE
alertmanager-main         97d
blackbox-exporter         97d
coredns                   97d
example-app               92d
grafana                   97d
kube-apiserver            97d
kube-controller-manager   97d
kube-scheduler            97d
kube-state-metrics        97d
kubelet                   97d
node-exporter             97d
prometheus-adapter        97d
prometheus-k8s            97d
prometheus-operator       97d
</code></pre> 
<p>查看创建的 Service:</p> 
<pre><code>kubectl get svc -n monitoring
NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
alertmanager-main       ClusterIP   10.110.204.224   &lt;none&gt;        9093/TCP            23h
alertmanager-operated   ClusterIP   None             &lt;none&gt;        9093/TCP,6783/TCP   23h
grafana                 ClusterIP   10.98.191.31     &lt;none&gt;        3000/TCP            23h
kube-state-metrics      ClusterIP   None             &lt;none&gt;        8443/TCP,9443/TCP   23h
node-exporter           ClusterIP   None             &lt;none&gt;        9100/TCP            23h
prometheus-adapter      ClusterIP   10.107.201.172   &lt;none&gt;        443/TCP             23h
prometheus-k8s          ClusterIP   10.107.105.53    &lt;none&gt;        9090/TCP            23h
prometheus-operated     ClusterIP   None             &lt;none&gt;        9090/TCP            23h
prometheus-operator     ClusterIP   None             &lt;none&gt;        8080/TCP            23h
</code></pre> 
<p>可以看到上面针对 grafana 和 prometheus 都创建了一个类型为 ClusterIP 的 Service，当然如果我们想要在外网访问这两个服务的话可以通过创建对应的 Ingress 对象或者使用 NodePort 类型的 Service。</p> 
<h3><a id="Prometheus_168"></a>访问Prometheus</h3> 
<p>可以使用以下工具快速访问Prometheus、Alertmanager和Grafana仪表板<code>kubectl port-forward</code>通过以下命令运行快速入门后。</p> 
<pre><code>kubectl --namespace monitoring port-forward svc/prometheus-k8s 9090
</code></pre> 
<p>在浏览器打开Prometheus <a href="http://localhost:9090/" rel="nofollow">localhost:9090</a> .</p> 
<p>查看 警报 <code>http://localhost:9090/alerts</code>和 规则 <code>http://localhost:9090/rules</code> 带有预配置规则和警报的页面！<br> 这个普罗米修斯应该监控你的Kubernetes集群，并确保在它出现问题时提醒你。</p> 
<p>对于您自己的应用程序，我们建议运行一个或多个其他实例。</p> 
<h3><a id="Alertmanager_183"></a>访问Alertmanager</h3> 
<pre><code>kubectl --namespace monitoring port-forward svc/alertmanager-main 9093
</code></pre> 
<h3><a id="Grafana_189"></a>访问Grafana</h3> 
<pre><code>kubectl --namespace monitoring port-forward svc/grafana 3000
</code></pre> 
<p>打开Grafana <a href="http://localhost:3000/" rel="nofollow">本地主机:3000</a>在您的浏览器中。<br> 您可以使用用户名登录<code>admin</code>和密码<code>admin</code>.</p> 
<h3><a id="kubeprometheus_198"></a>移除kube-prometheus</h3> 
<p>如果您已经完成了kube-prometheus和prometheus Operator 的实验，您可以通过运行以下命令来简单地拆除部署:</p> 
<pre><code>kubectl delete --ignore-not-found=true -f manifests/ -f manifests/setup
</code></pre> 
<h3><a id="_206"></a>配置</h3> 
<p>安装完成后，我们就可以通过去访问上面的两个服务了，比如查看 prometheus 的 service-discovery页面：</p> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/2398b29c81f9f8d3000913774fc1c947.png#pic_center" alt="image-20221214092332515"></p> 
<p>我们可以看到大部分的配置都是正常的，只有两三个没有管理到对应的监控目标，比如 kube-controller-manager 和 kube-scheduler 这两个系统组件，这就和 ServiceMonitor 的定义有关系了，我们先来查看下 kube-scheduler 组件对应的 ServiceMonitor 资源的定义：(prometheus-serviceMonitorKubeScheduler.yaml)</p> 
<pre><code>apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  labels:
    k8s-app: kube-scheduler
  name: kube-scheduler
  namespace: monitoring
spec:
  endpoints:
    - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
      interval: 30s
      port: https-metrics
      scheme: https
      tlsConfig:
        insecureSkipVerify: true
  jobLabel: app.kubernetes.io/name
  namespaceSelector:
    matchNames:
      - kube-system
  selector:
    matchLabels:
      app.kubernetes.io/name: kube-scheduler
</code></pre> 
<p>上面是一个典型的 ServiceMonitor 资源文件的声明方式，上面我们通过<code>selector.matchLabels</code>在 kube-system 这个命名空间下面匹配具有<code>app.kubernetes.io/name=kube-scheduler</code>这样的 Service，但是我们系统中根本就没有对应的 Service，所以我们需要手动创建一个 Service：（prometheus-kubeSchedulerService.yaml）</p> 
<pre><code>apiVersion: v1
kind: Service
metadata:
  namespace: kube-system
  name: kube-scheduler
  labels:
    app.kubernetes.io/name: kube-controller-manager
spec:
  selector:
    component: kube-controller-manager
  ports:
  - name: https-metrics
    port: 10257
    targetPort: 10257
    protocol: TCP
</code></pre> 
<p>其中最重要的是上面 labels 和 selector 部分，labels 区域的配置必须和我们上面的 ServiceMonitor 对象中的 selector 保持一致，<code>selector</code>下面配置的是<code>component=kube-scheduler</code>，为什么会是这个 label 标签呢，我们可以去 describe 下 kube-scheduelr 这个 Pod：</p> 
<pre><code>$ kubectl describe pod kube-scheduler-master -n kube-system
Name:         kube-scheduler-master
Namespace:    kube-system
Node:         master/10.151.30.57
Start Time:   Sun, 05 Aug 2018 18:13:32 +0800
Labels:       component=kube-scheduler
              tier=control-plane
......
</code></pre> 
<p>创建完成后，隔一小会儿后去 prometheus 查看 targets 下面 kube-scheduler 的状态：</p> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/5af054d027659cd64bde92a291ae4f92.png#pic_center" alt="*promethus kube-scheduler error*"></p> 
<p>我们可以看到现在已经发现了 target，但是抓取数据结果出错了，这个错误是因为我们集群是使用 kubeadm 搭建的，其中 kube-scheduler 默认是绑定在<code>127.0.0.1</code>上面的，而上面我们这个地方是想通过节点的 IP 去访问，所以访问被拒绝了，我们只要把 kube-scheduler 绑定的地址更改成<code>0.0.0.0</code>即可满足要求，由于 kube-scheduler 是以静态 Pod 的形式运行在集群中的，所以我们只需要更改静态 Pod 目录下面对应的 YAML 文件即可：</p> 
<pre><code>$ ls /etc/kubernetes/manifests/
etcd.yaml  kube-apiserver.yaml  kube-controller-manager.yaml  kube-scheduler.yaml
</code></pre> 
<p>将 kube-scheduler.yaml 文件中<code>-command</code>的<code>--address</code>地址更改成<code>0.0.0.0</code>：</p> 
<p>修改完成后我们将该文件从当前文件夹中移除，隔一会儿再移回该目录，就可以自动更新了，然后再去看 prometheus 中 kube-scheduler 这个 target 是否已经正常了：</p> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/375e34197248c43eb2e22a4d626f758e.png#pic_center" alt="operator-kube-scheduler"></p> 
<p>大家可以按照上面的方法尝试去修复下 kube-controller-manager 组件的监控。</p> 
<h2><a id="_297"></a>入门监控实例</h2> 
<h3><a id="_299"></a>部署示例应用程序</h3> 
<p>首先，让我们部署一个简单的示例应用程序，它有3个副本，监听并公开端口上的指标<code>8080</code>.</p> 
<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: example-app
  template:
    metadata:
      labels:
        app: example-app
    spec:
      containers:
      - name: example-app
        image: fabxc/instrumented_app
        ports:
        - name: web
          containerPort: 8080
</code></pre> 
<p>我们用一个<code>Service</code> 来绑定这些pod。并且暴露 8080 。</p> 
<pre><code>kind: Service
apiVersion: v1
metadata:
  name: example-app
  labels:
    app: example-app
spec:
  selector:
    app: example-app
  ports:
  - name: web
    port: 8080
</code></pre> 
<p>最后，我们创建一个ServiceMonitor对象来根据label自动发现需要监控的服务（example-app），它选择<code>app: example-app</code>标签。<code>ServiceMonitor</code>对象也有一个<code>team</code>标签(在这种情况下<code>team: frontend</code>)来确定哪个团队负责监控 pod或者service。</p> 
<pre><code>apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: example-app
  labels:
    team: frontend
spec:
  selector:
    matchLabels:
      app: example-app
  endpoints:
  - port: web
</code></pre> 
<h3><a id="_Prometheus_360"></a>部署 Prometheus</h3> 
<p>如果您的集群使用的是<a href="https://kubernetes.io/docs/reference/access-authn-authz/authorization/" rel="nofollow">RBAC</a>授权方式，您必须先为Prometheus服务帐户创建RBAC规则。</p> 
<p>应用以下清单来创建服务帐户和所需的<code>ClusterRole/ClusterRoleBinding</code>:</p> 
<pre><code>apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
</code></pre> 
<pre><code>apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus
rules:
- apiGroups: [""]
  resources:
  - nodes
  - nodes/metrics
  - services
  - endpoints
  - pods
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources:
  - configmaps
  verbs: ["get"]
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
  verbs: ["get"]
</code></pre> 
<pre><code>apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
- kind: ServiceAccount
  name: prometheus
  namespace: default
</code></pre> 
<p>Prometheus 自定义资源(CRD)定义了底层具体状态集的特征(副本数量、资源请求/限制等)以及应包含哪些服务监视器<code>spec.serviceMonitorSelector</code>字段。</p> 
<p>我们已经使用<code>team: frontend</code>标签，这里我们定义Prometheus对象应该选择所有带有<code>team: frontend</code>标签。这使得<code>frontend</code>团队能够创建新的服务监视器和服务，而不必重新配置Prometheus对象。</p> 
<pre><code>apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: prometheus
spec:
  namespaceSelector:{}
  serviceAccountName: prometheus
  serviceMonitorNamespaceSelector: {}
  serviceMonitorSelector:
    matchLabels:
      team: frontend
  resources:
    requests:
      memory: 400Mi
  enableAdminAPI: false
</code></pre> 
<p>要验证实例已启动并正在运行，运行:</p> 
<pre><code>kubectl get -n default prometheus prometheus -w
</code></pre> 
<p>默认情况下，Prometheus将只从<strong>当前命名空间</strong>中选取ServiceMonitors。若要从其他命名空间中选择ServiceMonitors，可以更新<code>spec.serviceMonitorNamespaceSelector</code>Prometheus resource 资源领域。</p> 
<p>选择所有的<strong>namespace</strong></p> 
<pre><code>namespaceSelector:
    any: true
</code></pre> 
<p>选择指定的 <strong>namespace</strong></p> 
<pre><code>  namespaceSelector:
    matchNames:
      - prod
</code></pre> 
<h3><a id="_PodMonitors_462"></a>使用 PodMonitors</h3> 
<p>我们可以使用PodMonitor来代替ServiceMonitor。在实践中<code>spec.selector</code>标签告诉Prometheus应该选择的pod。</p> 
<pre><code>apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
  name: example-app
  labels:
    team: frontend
spec:
  selector:
    matchLabels:
      app: example-app
  namespaceSelector: {}
  podMetricsEndpoints:
  - port: web
    interval: 15s
    path: /metrics
</code></pre> 
<p>类似地，Prometheus对象定义了用<code>spec.podMonitorSelector</code>字段。</p> 
<pre><code>apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: prometheus
spec:
  serviceAccountName: prometheus
  podMonitorSelector:
    matchLabels:
      team: frontend
  resources:
    requests:
      memory: 400Mi
  enableAdminAPI: false
</code></pre> 
<h3><a id="_Prometheus_service_502"></a>访问 Prometheus service</h3> 
<p>要访问Prometheus接口，您必须向外部公开服务。为了简单起见，我们使用一个<code>NodePort</code>服务。</p> 
<blockquote> 
 <p>当然也可以使用Ingress</p> 
</blockquote> 
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: prometheus
spec:
  type: NodePort
  ports:
  - name: web
    nodePort: 30900
    port: 9090
    protocol: TCP
    targetPort: web
  selector:
    prometheus: prometheus
</code></pre> 
<p>一旦创建了服务，Prometheus web服务器就可以在端口上的节点IP地址下使用了<code>30900</code>。web界面中的Targets页面应该显示已经成功发现了示例应用程序的实例。</p> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/5d2f1244424efbb56c56c5bed2a97b14.png#pic_center" alt="image-20221116162405790"></p> 
<h3><a id="Prometheus_Admin_API_531"></a>Prometheus Admin API</h3> 
<p>Prometheus Admin API允许访问删除特定时间范围内的series (数据)，清理tombstones，捕捉快照等。关于admin API的更多信息可以在<a href="https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-admin-apis" rel="nofollow">Prometheus 官方文档</a>默认情况下，此API访问是禁用的，可以使用此bool标志进行切换。以下示例公开了管理API:</p> 
<blockquote> 
 <p>警告:启用管理API会启用变异端点、删除数据、关闭Prometheus等等。启用此功能时应小心谨慎，建议用户通过代理添加额外的身份验证/授权，以确保只有获得授权的客户端才能执行这些操作。</p> 
</blockquote> 
<pre><code>apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: prometheus
spec:
  serviceAccountName: prometheus
  serviceMonitorSelector:
    matchLabels:
      team: frontend
  resources:
    requests:
      memory: 400Mi
  enableAdminAPI: true
</code></pre> 
<h2><a id="Alerting_553"></a>Alerting</h2> 
<blockquote> 
 <p>在Prometheus中定义AlertRule（告警规则 PrometheusRule），Prometheus会周期性的对告警规则进行计算，如果满足告警触发条件就会向Alertmanager发送告警信息。Alertmanager 再经过分组、抑制以及静默发送到 对应的receiver</p> 
</blockquote> 
<p>Prometheus Operator引入了一个<code>Alertmanager</code>资源，该资源允许用户以声明方式描述Alertmanager集群。要成功部署Alertmanager集群，理解Prometheus和Alertmanager之间的契约非常重要。Alertmanager用于:</p> 
<ul><li>对从Prometheus收到的警报进行重复数据去重。</li><li>静音提示。</li><li>将分组通知路由和发送到各种集成(PagerDuty、OpsGenie、mail、chat等)。</li></ul> 
<p>Prometheus Operator还引入了一个<code>AlertmanagerConfig</code>资源，它允许用户以声明方式描述Alertmanager配置。</p> 
<p>Prometheus的配置还包括“rule files”，其中包含<a href="https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/" rel="nofollow">警报规则 alerting rules</a>。当一个警报规则触发时，它会触发该警报<em>全部</em>Alertmanager实例，打开<em>每个</em>规则评估间隔。Alertmanager实例相互交流哪些通知已经发出。有关此系统设计的更多信息，请参见<a href="https://prometheus-operator.dev/docs/operator/high-availability/" rel="nofollow">高可用性</a>页面。</p> 
<h3><a id="_Alertmanager_567"></a>部署 Alertmanager</h3> 
<p>首先，创建一个包含三个副本的Alertmanager集群:</p> 
<pre><code>apiVersion: monitoring.coreos.com/v1
kind: Alertmanager
metadata:
  name: example
spec:
  replicas: 3
</code></pre> 
<p>等待所有报警管理器盒准备就绪:</p> 
<pre><code>kubectl get pods -l alertmanager=example -w
</code></pre> 
<h3><a id="_Alertmanager_configuration_586"></a>管理 Alertmanager configuration</h3> 
<p>默认情况下，Alertmanager实例将以最小的配置启动，这并不是真正有用的，因为它没有报警配置，所以在接收警报时不会发送任何通知。</p> 
<p>你需要用下面几种选择来提供<a href="https://andyoung.blog.csdn.net/article/details/126243110" rel="nofollow">警报管理器配置</a>:</p> 
<ul><li> 
  <ol><li>您可以使用存储在Kubernetes secret中的本地Alertmanager配置文件。</li></ol> </li><li> 
  <ol start="2"><li>你可以用<code>spec.alertmanagerConfiguration</code>在定义主Alertmanager配置的同一命名空间中引用AlertmanagerConfig对象。</li></ol> </li><li> 
  <ol start="3"><li>你可以定义<code>spec.alertmanagerConfigSelector</code>和<code>spec.alertmanagerConfigNamespaceSelector</code>告诉operator 应该选择哪些AlertmanagerConfigs对象并将其与主Alertmanager配置合并。</li></ol> </li></ul> 
<h4><a id="1__Kubernetes_Secret_596"></a>1. 使用 Kubernetes Secret</h4> 
<p>以下本机Alertmanager配置向外部的webhook服务发送通知：</p> 
<pre><code>route:
  group_by: ['job']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 12h
  receiver: 'webhook'
receivers:
- name: 'webhook'
  webhook_configs:
  - url: 'http://example.com/'
</code></pre> 
<p>将上述配置保存在一个名为<code>alertmanager.yaml</code>并从中创建一个<code>Secret </code>:</p> 
<pre><code>kubectl create secret generic alertmanager-example --from-file=alertmanager.yaml
</code></pre> 
<p>Prometheus operator要求<code>Secret </code>的命名要像<code>alertmanager-{ALERTMANAGER_NAME}</code>。在前面的示例中，Alertmanager的名称是<code>example</code>，所以Secret名必须是<code>alertmanager-example</code>。<code>Secret </code>中保存配置数据的密钥的名称必须是<code>alertmanager.yaml</code>.</p> 
<blockquote> 
 <p>注意:如果要使用不同的<code>Secret</code>名称，可以用<code>spec.configSecret</code>Alertmanager资源中的字段。</p> 
</blockquote> 
<p>Alertmanager配置可能会引用磁盘上的自定义模板或<code>Secret</code>文件。这些可以和<code>alertmanager.yaml</code>配置文件。例如，假设我们有以下<code>Secret</code>:</p> 
<pre><code>apiVersion: v1
kind: Secret
metadata:
  name: alertmanager-example
data:
  alertmanager.yaml: {BASE64_CONFIG}
  template_1.tmpl: {BASE64_TEMPLATE_1}
  template_2.tmpl: {BASE64_TEMPLATE_2}
</code></pre> 
<p>Alertmanager容器也可以访问模板比如<code>/etc/alertmanager/config</code>目录。Alertmanager配置可以像这样引用它们:</p> 
<pre><code>templates:
- '/etc/alertmanager/config/*.tmpl'
</code></pre> 
<h4><a id="2_AlertmanagerConfig_Resources_643"></a>2. 使用AlertmanagerConfig Resources</h4> 
<p>以下示例配置创建了一个向webhook服务发送通知的AlertmanagerConfig资源。</p> 
<pre><code>apiVersion: monitoring.coreos.com/v1alpha1
kind: AlertmanagerConfig
metadata:
  name: config-example
  labels:
    alertmanagerConfig: example
spec:
  route:
    groupBy: ['job']
    groupWait: 30s
    groupInterval: 5m
    repeatInterval: 12h
    receiver: 'webhook'
  receivers:
  - name: 'webhook'
    webhookConfigs:
    - url: 'http://example.com/'
</code></pre> 
<p>在群集中创建AlertmanagerConfig资源:</p> 
<pre><code>curl -sL https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/main/example/user-guides/alerting/alertmanager-config-example.yaml | kubectl create -f -
</code></pre> 
<p>这<code>spec.alertmanagerConfigSelector</code>需要更新Alertmanager资源中的字段，以便operator选择AlertmanagerConfig资源。在前面的示例中，标签<code>alertmanagerConfig: example</code>所以Alertmanager对象应该像这样更新:</p> 
<pre><code>apiVersion: monitoring.coreos.com/v1
kind: Alertmanager
metadata:
  name: example
spec:
  replicas: 3
  alertmanagerConfigSelector:
    matchLabels:
      alertmanagerConfig: example
</code></pre> 
<h4><a id="3_AlertmanagerConfig_689"></a>3. 使用AlertmanagerConfig进行全局配置</h4> 
<p>下面的示例配置创建一个Alertmanager资源，该资源使用AlertmanagerConfig资源来代替<code>alertmanager-example</code>secret。</p> 
<pre><code>apiVersion: monitoring.coreos.com/v1
kind: Alertmanager
metadata:
  name: example
  namespace: default
spec:
  replicas: 3
  alertmanagerConfiguration:
    name: config-example
</code></pre> 
<p>名为<code>example-config</code>的AlertmanagerConfig资源在命名空间中<code>default</code>将是一个全局警报管理器配置。当operator 从中生成Alertmanager配置时，不会对路由和禁止规则强制使用名称空间标签。</p> 
<h3><a id="_Alertmanager_service_709"></a>暴露 Alertmanager service</h3> 
<p>要访问Alertmanager接口，必须向外部公开服务。为了简单起见，我们使用一个<code>NodePort</code>服务。</p> 
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: alertmanager-example
spec:
  type: NodePort
  ports:
  - name: web
    nodePort: 30903
    port: 9093
    protocol: TCP
    targetPort: web
  selector:
    alertmanager: example
</code></pre> 
<p>创建服务后，Alertmanager web服务器就可以在节点的IP地址端口下使用了<code>30903</code>.</p> 
<h3><a id="Prometheus_732"></a>与Prometheus整合</h3> 
<h4><a id="PrometheusAlertmanager_734"></a>在Prometheus中配置Alertmanager</h4> 
<p>这个Alertmanager集群现在功能齐全且高度可用，但是没有针对它触发任何警报。</p> 
<p>首先，创建一个Prometheus实例，它将向Alertmanger集群发送警报:</p> 
<pre><code>apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: example
spec:
  serviceAccountName: prometheus
  replicas: 2
  alerting:
    alertmanagers:
    - namespace: default
      name: alertmanager-example
      port: web
  serviceMonitorSelector:
    matchLabels:
      team: frontend
  ruleSelector:
    matchLabels:
      role: alert-rules
      prometheus: example
</code></pre> 
<p>这<code>Prometheus</code>资源发现<code>Service</code>之前创建的(注意<code>name</code>, <code>namespace</code>和<code>port</code>应该与Alertmanager服务的定义相匹配的字段)。</p> 
<p>打开Prometheus web界面，转到“Status &gt; Runtime &amp; Build Information”页面，检查Prometheus是否发现了3个Alertmanager实例。</p> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/d9f6e83bf278978a377106ae25b19ce3.png#pic_center" alt="image-20221116173224665"></p> 
<h4><a id="_Prometheus_Rules_768"></a>部署 Prometheus Rules</h4> 
<p><code>PrometheusRule</code>CRD允许定义警报和<strong>记录规则</strong>。operator 知道为给定的Prometheus 选择哪个PrometheusRule 对象<code>spec.ruleSelector</code>字段。</p> 
<blockquote> 
 <p>注意:默认情况下，<code>spec.ruleSelector</code>为nil意味着操作符没有选择任何规则。</p> 
</blockquote> 
<p>默认情况下，Prometheus resources 仅发现<code>PrometheusRule</code>同一命名空间中的资源。这可以用<code>ruleNamespaceSelector</code>字段:</p> 
<ul><li>要从所有名称空间中发现规则，传递一个空的<code>{}</code>(<code>ruleNamespaceSelector: {}</code>).</li><li>若要从匹配某个标签的所有命名空间中发现规则，请使用<code>matchLabels</code>字段。</li></ul> 
<p>Prometheus 会自动发现<code>PrometheusRule</code>资源与<code>role=alert-rules</code>和<code>prometheus=example</code>来自所有命名空间的标签<code>team=frontend</code>标签:</p> 
<pre><code>apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: example
spec:
  serviceAccountName: prometheus
  replicas: 2
  alerting:
    alertmanagers:
    - namespace: default
      name: alertmanager-example
      port: web
  serviceMonitorSelector:
    matchLabels:
      team: frontend
  ruleSelector:
    matchLabels:
      role: alert-rules
      prometheus: example
  ruleNamespaceSelector:
    matchLabels:
      team: frontend
</code></pre> 
<p>如果您想按名称选择单个命名空间，可以使用<code>kubernetes.io/metadata.name</code>标签，它会自动用<a href="https://kubernetes.io/docs/reference/labels-annotations-taints/#kubernetes-io-metadata-name" rel="nofollow"><code>NamespaceDefaultLabelName</code></a>功能。</p> 
<pre><code>apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  creationTimestamp: null
  labels:
    prometheus: example
    role: alert-rules
  name: prometheus-example-rules
spec:
  groups:
  - name: ./example.rules
    rules:
    - alert: ExampleAlert
      expr: vector(1)
</code></pre> 
<p>创建<code>PrometheusRule</code>对象。请注意，对象的标签与<code>spec.ruleSelector</code>Prometheus 配置的相对应</p> 
<pre><code>apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  creationTimestamp: null
  labels:
    prometheus: example
    role: alert-rules
  name: prometheus-example-rules
spec:
  groups:
  - name: ./example.rules
    rules:
    - alert: ExampleAlert
      expr: vector(1)
</code></pre> 
<pre><code>apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  creationTimestamp: null
  labels:
    prometheus: k8s
    role: alert-rules
  name: prometheus-example-rules
spec:
  groups:
    - name: hostStatsAlert
      rules:
      - alert: hostCpuUsageAlert
        expr: sum(avg without (cpu)(irate(node_cpu_seconds_total{mode!='idle'}[5m]))) by (instance) &gt; 0.5
        for: 1m
        labels:
          severity: page
        annotations:
          summary: "Instance {<!-- -->{ $labels.instance }} CPU usgae high"
          description: "{<!-- -->{ $labels.instance }} CPU usage above 85% (current value: {<!-- -->{ $value }})"
      - alert: hostMemUsageAlert
        expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes)/node_memory_MemTotal_bytes &gt; 0.5
        for: 1m
        labels:
          severity: page
        annotations:
          summary: "Instance {<!-- -->{ $labels.instance }} MEM usgae high"
          description: "{<!-- -->{ $labels.instance }} MEM usage above 85% (current value: {<!-- -->{ $value }})"
</code></pre> 
<h2><a id="_877"></a>那些坑</h2> 
<h3><a id="Prometheus_Operator__879"></a>Prometheus Operator 高可用设计</h3> 
<h4><a id="Prometheus___881"></a>Prometheus 高可用</h4> 
<p>Prometheus Operator 暂不支持 高可通设计还在规划中，详情参考官方文档 <a href="https://prometheus-operator.dev/docs/operator/high-availability/" rel="nofollow">https://prometheus-operator.dev/docs/operator/high-availability/</a></p> 
<h4><a id="Alertmanager_885"></a>Alertmanager</h4> 
<p>通过Gossip协议实现高可用，部署完之后自动形成集群</p> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/127ce8eba56577e0d709847647a0eaa6.png#pic_center" alt="Alertmanager集群"></p> 
<p>Prometheus 高可用参考：<a href="https://blog.csdn.net/agonie201218/article/details/126249715">【Prometheus】Prometheus 集群与高可用 </a></p> 
<h3><a id="Prometheus__895"></a>Prometheus 支持远程读写</h3> 
<pre><code>kubectl explain Prometheus.spec.remoteRead
</code></pre> 
<h3><a id="tsdb__901"></a>tsdb 保留天数</h3> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/406e94c2cb89979bf8b4963f8b72ec78.png" alt="tsdb 保留天数"><br> 默认情况下Prometheus Operator 的 tsdb（–storage.tsdb.retention.time） 只保留1天，这里我们需要要在自己的意愿把他变成<br> 使用explain 查看Prometheus 资源结构</p> 
<pre><code>kubectl explain Prometheus.spec
</code></pre> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/ef69c75335940f96304dbe1a82cc1e9a.png" alt="在这里插入图片描述"><br> 可以查看到有 retention 保留设置</p> 
<pre><code>kind: Prometheus
apiVersion: monitoring.coreos.com/v1 
...
spec:
  ...
  retention: 15d
</code></pre> 
<p>结果<br> <img src="https://i-blog.csdnimg.cn/blog_migrate/f6a3b9d0b78e2c0787c2d05dbd8fd656.png" alt="在这里插入图片描述"></p> 
<h2><a id="_924"></a>参考</h2> 
<p><a href="https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#monitoring.coreos.com/v1.RemoteReadSpec">查看Prometheus 资源结构</a></p> 
<p><a href="https://www.qikqiak.com/k8s-book/" rel="nofollow">https://www.qikqiak.com/k8s-book/</a></p>
                </div>
            </body>
            </html>
            